package com.cjt.chat.service;

import com.cjt.chat.config.GetHttpSessionConfig;
import com.cjt.chat.mapper.GroupMapper;
import com.cjt.chat.mapper.MessageMapper;
import com.cjt.chat.mapper.UserMapper;
import com.cjt.chat.pojo.GroupMessage;
import com.cjt.chat.pojo.Message;
import com.cjt.chat.pojo.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import static com.fasterxml.jackson.core.json.JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER;

/**
 * @author cjt
 * @since 2024/3/27
 */
@ServerEndpoint(value = "/api/websocket/{user_id}", configurator = GetHttpSessionConfig.class)
@Component
public class WebSocketServer {

    //当前在线连接数
    private final static AtomicInteger onlineCount = new AtomicInteger(0);

    //用来存放每个客户端对应的WebSocketServer对象
    private final static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    //用户id
    private String userid;
    //用户当前会话
    private Session session;
    //HttpSession 用于验证发送消息的用户是否合法
    private HttpSession httpSession;

    private static ApplicationContext applicationContext;


    /**
     * 连接建立成功
     *
     * @param session 与客户端建立的会话对象
     * @param userid  用户id
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("user_id") String userid, EndpointConfig endpointConfig) {
        this.session = session;
        this.userid = userid;
        this.httpSession = (HttpSession) endpointConfig.getUserProperties().get("httpSession");
        if (webSocketMap.containsKey(userid)) {
            webSocketMap.remove(userid);
            webSocketMap.put(userid, this);
        } else {
            webSocketMap.put(userid, this);
        }
        addOnlineUser();
        System.out.println("用户:" + userid + "登录成功");
        String message = "{\"messageType\": \"connection-success\",\"message\": \"用户:" + userid + " 连接成功!\"}";
        sendMessage(message);
        System.out.println("当前在线人数:" + getOnlineCount());
    }

    @OnClose
    public void onClose() {
        webSocketMap.remove(userid);
        subOnlineUser();
        System.out.println("用户:" + userid + "退出登录");
        System.out.println("当前在线人数:" + getOnlineCount());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println(message);
        User user = (User) httpSession.getAttribute("user");
        JsonMapper objectMapper = JsonMapper.builder().enable(ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER).build();

        if (user != null && userid.equals(user.getUserid().toString())) {
            try {
                JsonNode jsonNode = objectMapper.readTree(message);
                String messageType = jsonNode.get("messageType").asText();
                if ("nomal".equals(messageType)) {
                    sendMessageToUser(objectMapper, message);
                }
                if ("group".equals(messageType)) {
                    sendMessageToGroup(objectMapper, message);
                }
                if ("friendRequest".equals(messageType)) {
                    sendFriendRequest(objectMapper, message);
                }
                if ("joinGroupRequest".equals(messageType)) {
                    sendJoinGroupRequest(objectMapper, message);
                }
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        } else {
            sendMessage("{\"messageType\": \"warning\",\"message\": \"发送失败\"}");
        }
    }

    private void sendJoinGroupRequest(JsonMapper objectMapper, String message) throws JsonProcessingException {
        Message value = objectMapper.readValue(message, Message.class);
        value.setMessageTime(System.currentTimeMillis());

        //将毫秒数时间格式化
        Long messageTime = value.getMessageTime();
        Instant instant = Instant.ofEpochMilli(messageTime);
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd-HH:mm:ss");
        String format = localDateTime.format(dtf);
        value.setDateFormat(format);

        MessageMapper messageMapper = WebSocketServer.applicationContext.getBean(MessageMapper.class);
        Integer count = messageMapper.queryIsJoinGroupRequest(value.getFrom(), value.getTo());
        System.out.println(count);
        if (count == 0) {
            GroupMapper groupMapper = WebSocketServer.applicationContext.getBean(GroupMapper.class);
            Integer masterId = groupMapper.queryGroupMasterId(value.getTo());

            WebSocketServer webSocketServer = WebSocketServer.webSocketMap.get(masterId.toString());

            //如果对方在线就直接发送
            if (webSocketServer != null) {
                String sendMessage = objectMapper.writeValueAsString(value);
                webSocketServer.sendMessage(sendMessage);
            }
            //将消息记录存入数据库
            MessageService messageService = WebSocketServer.applicationContext.getBean(MessageService.class);
            messageService.saveMessage(value);
        }
    }

    private void sendFriendRequest(ObjectMapper objectMapper, String message) throws JsonProcessingException {
        Message value = objectMapper.readValue(message, Message.class);
        value.setMessageTime(System.currentTimeMillis());

        //将毫秒数时间格式化
        Long messageTime = value.getMessageTime();
        Instant instant = Instant.ofEpochMilli(messageTime);
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd-HH:mm:ss");
        String format = localDateTime.format(dtf);
        value.setDateFormat(format);

        MessageMapper messageMapper = WebSocketServer.applicationContext.getBean(MessageMapper.class);
        Integer count = messageMapper.queryIsSendFriendRequest(value.getFrom(), value.getTo());
        if (count == 0) {
            Integer to = value.getTo();
            //获取目标用户
            WebSocketServer webSocketServer = WebSocketServer.webSocketMap.get(to.toString());

            //如果对方在线就直接发送
            if (webSocketServer != null) {
                String sendMessage = objectMapper.writeValueAsString(value);
                webSocketServer.sendMessage(sendMessage);
            }
            //将消息记录存入数据库
            MessageService messageService = WebSocketServer.applicationContext.getBean(MessageService.class);
            messageService.saveMessage(value);
        }
    }

    //单对单消息
    private void sendMessageToUser(ObjectMapper objectMapper, String message) throws JsonProcessingException {
        Message value = objectMapper.readValue(message, Message.class);
        value.setMessageTime(System.currentTimeMillis());

        //将毫秒数时间格式化
        Long messageTime = value.getMessageTime();
        Instant instant = Instant.ofEpochMilli(messageTime);
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd-HH:mm:ss");
        String format = localDateTime.format(dtf);
        value.setDateFormat(format);

        Integer to = value.getTo();
        //获取目标用户
        WebSocketServer webSocketServer = WebSocketServer.webSocketMap.get(to.toString());

        //如果对方在线就直接发送
        if (webSocketServer != null) {
            String sendMessage = objectMapper.writeValueAsString(value);
            webSocketServer.sendMessage(sendMessage);
        }
        //将消息记录存入数据库
        MessageService messageService = WebSocketServer.applicationContext.getBean(MessageService.class);
        messageService.saveMessage(value);
    }

    //消息类型是group
    private void sendMessageToGroup(ObjectMapper objectMapper, String message) throws JsonProcessingException {
        GroupMessage groupMessage = objectMapper.readValue(message, GroupMessage.class);
        groupMessage.setMessageTime(System.currentTimeMillis());

        //将毫秒数时间格式化
        Long messageTime = groupMessage.getMessageTime();
        Instant instant = Instant.ofEpochMilli(messageTime);
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd-HH:mm:ss");
        String format = localDateTime.format(dtf);
        groupMessage.setDateFormat(format);

        //获取群组所有成员
        GroupService groupService = applicationContext.getBean(GroupService.class);
        UserMapper userMapper = applicationContext.getBean(UserMapper.class);
        //获取用户头像url和昵称
        User sender = userMapper.queryUserByUserId(groupMessage.getSenderId());

        groupMessage.setSenderHead(sender.getHeadImage());
        groupMessage.setSenderPetName(sender.getPetName());
        List<User> groupMemberList = groupService.getGroupMemberList(groupMessage.getGroupId());
        //将消息发送给除了发送者之外所有在线群组成员
        for (User user : groupMemberList) {
            if (!user.getUserid().equals(groupMessage.getSenderId())) {
                WebSocketServer webSocketServer = webSocketMap.get(user.getUserid().toString());
                if (webSocketServer != null) {
                    String group = objectMapper.writeValueAsString(groupMessage);
                    webSocketServer.sendMessage(group);
                }
            }
        }
        //将群消息持久化保存
        groupService.saveGroupMessage(groupMessage);
    }

    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取当前在线用户数量
    public synchronized int getOnlineCount() {
        return onlineCount.get();
    }

    //增加在线用户数量
    public synchronized void addOnlineUser() {
        WebSocketServer.onlineCount.getAndIncrement();
    }

    //减少在线用户数量
    public synchronized void subOnlineUser() {
        WebSocketServer.onlineCount.getAndDecrement();
    }

    public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketServer.applicationContext = applicationContext;
    }
}
